#ifndef __REFLECTION_HH__
#define __REFLECTION_HH__

#include <boost/shared_ptr.hpp>

#include "EmptyType.hh"
#include "Reflection/TypeDcl.hh"
#include "Reflection/Property.hh"
#include "Reflection/BindedProperty.hh"
#include "Reflection/Class.hh"
#include "Reflection/BaseClass.hh"
#include "Meta/If.hh"

using namespace Common;

namespace Reflection
{

////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////
template< typename... TProperty >
struct PropertyContainerSize;

template< typename THead, typename... TTail >
struct PropertyContainerSize< THead, TTail... >
{
    enum{ value = PropertyContainerSize< TTail... >::value + 1 };
};
    
template<>
struct PropertyContainerSize<>
{
    enum{ value = 0 };
};

/////////////////////////////////////////////////////////////////////////////////////////
template< template< typename > class TPred, typename... TProperty >
struct PropertyFindIf;

template< template< typename > class TPred, typename THead, typename... TTail >
struct PropertyFindIf< TPred, THead, TTail... >
{
    typedef typename Meta::If<
                      THead
                    , typename PropertyFindIf< TPred, TTail...>::Value
                    , TPred< THead >::value
                  >::Value Value;
};

template< template< typename > class TPred >
struct PropertyFindIf< TPred >
{
    typedef EmptyType Value;
};
//////////////////////////////////////////////////////////////////////////////////////////

/**
 * @class BasePropertyContainer
 * @brief Base class for property container
 */
class BasePropertyContainer
{    
public:
    virtual size_t getSize( void ) = 0;
};


/**
 * @class PropertyContainer
 */
template< typename... TProperty >
class PropertyContainer : public BasePropertyContainer
{    
public:
    virtual size_t getSize( void ) { return PropertyContainerSize< TProperty... >::value; }
};

//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
} // namespace Reflection

#endif
